package org.damazio.bhtranscams;

import android.app.Activity;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.graphics.Bitmap;
import android.net.Uri;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.widget.ImageView;

/**
 * Activity for actually fetching and showing a camera's image.
 * 
 * @author rdamazio
 */
public class BHTransCamView extends Activity implements CameraFetcher.FetchDoneCallback {
  private static final String CAMERA_NAME_EXTRA = "org.damazio.bhtranscams.extra.camName";
  private static final String BHTRANS_BASE_URL = "http://infotrafego.pbh.gov.br/rlt/images/camera%02d.jpg";

  // Objects using during loading
  private ProgressDialog loadingDialog;
  private CameraFetcher cameraFetcher;

  // Objects using for auto-updating
  private CameraAutoUpdater autoUpdater;

  // Longer-lasting state
  private Bitmap lastBitmap;
  private String imageUrl;

  @Override
  public Object onRetainNonConfigurationInstance() {
    return lastBitmap;
  }

  @Override
  public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    setContentView(R.layout.camview);

    // Reads the intent
    String cameraName = getIntent().getExtras().getString(CAMERA_NAME_EXTRA);
    imageUrl = getIntent().getData().toString();

    // Sets the title
    String titleFormat = getString(R.string.camViewTitleFormat);
    String title = String.format(titleFormat, cameraName);
    setTitle(title);

    // Restores the last cached image if any
    lastBitmap = (Bitmap) getLastNonConfigurationInstance();

    autoUpdater = new CameraAutoUpdater(this, new Runnable() {
      public void run() { loadImage(imageUrl, false, false); }
    });
  }

  @Override
  protected void onResume() {
    super.onResume();

    // Loads the image
    loadImage(imageUrl, true, true);
  }

  @Override
  protected void onPause() {
    autoUpdater.cancel();

    super.onPause();
  }

  @Override
  protected void onDestroy() {
    if (cameraFetcher != null) {
      // Asked for destruction while still fetching
      cameraFetcher.cancel();
    }

    super.onDestroy();
  }

  /**
   * Loads the image from the given URL, optionally using the last cached image.
   * 
   * @param imageUrl is the URL of the image to load
   * @param fromCache whether to use the last cached image if available
   * @param showProgress TODO
   */
  private void loadImage(String imageUrl, boolean fromCache, boolean showProgress) {
    if (cameraFetcher != null) {
      // Already loading something
      return;
    }

    // If there was anything pending, cancel it
    autoUpdater.cancel();

    if (fromCache && lastBitmap != null) {
      // Be done fetching by using the cache
      onFetchDone(lastBitmap, imageUrl);
    } else {
      // Clear the cache
      lastBitmap = null;

      if (showProgress) {
        // Show a loading dialog
        loadingDialog = ProgressDialog.show(this, "", getString(R.string.loadingImage), true, true,
            new DialogInterface.OnCancelListener() {
              public void onCancel(DialogInterface dialog) {
                if (cameraFetcher != null) {
                  cameraFetcher.cancel();
                  finish();
                }
              }
            });
      }

      // Request fetching of the image
      cameraFetcher = new CameraFetcher(imageUrl, this);
      cameraFetcher.start();
    }
  }

  /**
   * Callback for when an image is done loading.
   */
  public void onFetchDone(Bitmap cameraImage, String fetchedUrl) {
    // Dismiss the loading dialog
    if (loadingDialog != null) {
      loadingDialog.dismiss();
      loadingDialog = null;
    }

    // Set the image on the UI
    ImageView camView = (ImageView) findViewById(R.id.camImage);
    camView.setImageBitmap(cameraImage);

    // Cache it
    lastBitmap = cameraImage;

    // Schedule the next update
    autoUpdater.schedule();

    // Discard the fetcher
    cameraFetcher = null;
  }

  @Override
  public boolean onCreateOptionsMenu(Menu menu) {
    // Load the menu
    MenuInflater inflater = getMenuInflater();
    inflater.inflate(R.menu.view_menu, menu);
    return true;
  }

  @Override
  public boolean onPrepareOptionsMenu(Menu menu) {
    // Choose the appropriate icon for the auto-update menu item
    boolean autoUpdateEnabled = autoUpdater.isEnabled();
    int autoUpdateIcon;
    if (autoUpdateEnabled) {
      autoUpdateIcon = android.R.drawable.button_onoff_indicator_on;
    } else {
      autoUpdateIcon = android.R.drawable.button_onoff_indicator_off;
    }

    // Update the icon on item
    MenuItem autoUpdateMenuItem = menu.findItem(R.id.autoUpdate);
    autoUpdateMenuItem.setIcon(autoUpdateIcon);

    return true;
  }

  @Override
  public boolean onOptionsItemSelected(MenuItem item) {
    switch (item.getItemId()) {
      case R.id.refresh: {
        // Explicit refresh request, never use the cache
        loadImage(imageUrl, false, true);
      }
      case R.id.autoUpdate: {
        boolean autoUpdate = !autoUpdater.isEnabled();
        autoUpdater.setEnabled(autoUpdate);
        autoUpdater.schedule();
        break;
      }
      case R.id.about: {
        startActivity(new Intent(this, BHTransCamsAbout.class));
      }
    }
    return true;
  }

  /**
   * Starts this activity with the proper intent.
   * 
   * @param context the current context from which to start the activity
   * @param camera the camera to display in this activity
   */
  public static void startCameraViewActivity(Context context, Cameras camera) {
    // Get camera properties
    int cameraNum = camera.getCameraNum();
    String cameraName = camera.getName();

    // Build its image's URL
    Uri cameraUri = Uri.parse(String.format(BHTRANS_BASE_URL, cameraNum));

    // Define the intent to display it
    Intent intent = new Intent();
    intent.setAction("org.damazio.bhtranscams.intent.CAM_VIEW");
    intent.setClass(context, BHTransCamView.class);
    intent.setDataAndType(cameraUri, "image/jpeg");
    intent.putExtra(CAMERA_NAME_EXTRA, cameraName);

    // Start it
    context.startActivity(intent);
  }
}
